﻿using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.ReportGenerator.BL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Sustainalytics.Reporting.BusinessLogic
{
    //public class PdfReportExecutor : IPdfReportExecutor
    //{
    //    public ExecutionResult ExecuteEsgReport(Guid companyId, Guid esgProfileId)
    //    {
    //        var crdos = GetCompanyReportDataOffline(new List<Guid>() { companyId });
    //        var crdo = crdos[0];
    //        crdo.ReportType = ReportGenerator.BL.ReportType.CompanyReport;

    //        var reportGenerator = new ReportGenerator.BL.ReportGenerator();
    //        var renderResult = reportGenerator.GenerateReportPdf(crdo.ReportType, crdo, true);

    //        return new ExecutionResult
    //        {
    //            Id = companyId,
    //            PdfDocument = renderResult.FileContent
    //        };
    //    }

    //    public ExecutionResult ExecuteControversyReport(Guid companyId)
    //    {

    //        var crdos = GetCompanyReportDataOffline(new List<Guid>() { companyId });
    //        var crdo = crdos[0];
    //        crdo.ReportType = ReportGenerator.BL.ReportType.CompanyReport;

    //        var reportGenerator = new ReportGenerator.BL.ReportGenerator();
    //        var renderResult = reportGenerator.GenerateReportPdf(crdo.ReportType, crdo, true);

    //        return new ExecutionResult
    //        {
    //            Id = companyId,
    //            PdfDocument = renderResult.FileContent
    //        };
    //    }


    //    public ExecutionResult ExecutePdfReport(PdfReportParameters reportParameters)
    //    {
            
    //        return new ExecutionResult
    //        {
    //            Id = reportParameters.CompanyId

    //        };
    //    }

    //    #region provisioning data

    //    private const DatabaseGroup CurrentDatabaseGroup = DatabaseGroup.B;
    //    private const string IpAddress = "54.72.160.155";

    //    private static readonly string ClientDwConnectionString = string.Format("mongodb://{0}:27017/ClientDW_{1}", IpAddress, CurrentDatabaseGroup);
    //    private static readonly string ClientPlatformConnectionString = string.Format("mongodb://{0}:27017/ClientPlatform", IpAddress);
    //    private static readonly string CompanyReportPdfConnectionString = string.Format("mongodb://{0}:27017/CompanyReportPDF_{1}", IpAddress, CurrentDatabaseGroup);
    //    private static readonly string ControversyReportPdfConnectionString = string.Format("mongodb://{0}:27017/ControversyReportPDF_{1}", IpAddress, CurrentDatabaseGroup);
    //    private static readonly string DwArchiveConnectionString = string.Format("mongodb://{0}:27017/DWArchive_{1}", IpAddress, CurrentDatabaseGroup);


    //    private static List<CompanyReportDataOffline> GetCompanyReportDataOffline(List<Guid> companyIds)
    //    {

    //        var defaultEsgProfile = (new RepositoryCollection<ESGProfile>(ClientPlatformConnectionString))
    //            .ReadAllWhereFieldEqualsValue("Name", "Default", null, 1).SingleOrDefault();


    //        var corporateDataRepo = new RepositoryCollection<CorporateData>(ClientDwConnectionString);
    //        var corporateData = corporateDataRepo.ReadbyIds(companyIds);

    //        var financialDataRepo = new RepositoryCollection<FinancialData>(ClientDwConnectionString);
    //        var financialData = financialDataRepo.ReadbyIds(companyIds, new string[] { "MarketCapitalization", "CompanyName" });

    //        var referenceDataRep = new RepositoryCollection<ReferenceData>(ClientDwConnectionString);
    //        var referenceData = referenceDataRep.ReadbyIds(companyIds);

    //        var companyPerformanceRepo = new RepositoryCollection<CompanyPerformance>(ClientDwConnectionString);
    //        var companyPerformance = companyPerformanceRepo.ReadbyIds(companyIds);

    //        var companyHistoricalPerformanceRepo = new RepositoryCollection<CompanyHistoricalPerformance>(DwArchiveConnectionString);
    //        var companyHistoricalPerformance = companyHistoricalPerformanceRepo.ReadbyIds(companyIds);

    //        var indicatorTemplatesRep = new RepositoryCollection<IndicatorTemplate>(ClientDwConnectionString);
    //        var indicatorTemplates = indicatorTemplatesRep.ReadAll();

    //        var analystRepo = new RepositoryCollection<Analyst>(ClientDwConnectionString);
    //        var analysts = analystRepo.ReadAll().ToDictionary(k => k.AnalystId, v => v);

    //        var gicsSubIndustryRepo = new RepositoryCollection<GICSSubIndustry>(ClientDwConnectionString);
    //        var gicsSubIndustries = gicsSubIndustryRepo.ReadAll().ToDictionary(k => k.Name, v => Convert.ToInt32(v.Number));

    //        var subIndustryKeyEsgIssues = new Dictionary<int, List<SubIndustryKeyEsgIssue>>();
    //        var subIndustryKeyEsgIssueRepo = new RepositoryCollection<SubIndustryKeyEsgIssue>(ClientDwConnectionString);
    //        var allSubIndustryKeyEsgIssues = subIndustryKeyEsgIssueRepo.ReadAll();
    //        var subIndustries = allSubIndustryKeyEsgIssues.GroupBy(x => x.SubIndustryCode).ToList();
    //        subIndustries.ForEach(x => subIndustryKeyEsgIssues.Add(x.Key, x.ToList()));

    //        var companyKeyEsgIssueRepo = new RepositoryCollection<CompanyKeyESGIssue>(ClientDwConnectionString);
    //        var companyKeyEsgIssues = companyKeyEsgIssueRepo.ReadAllWhere(x => companyIds.Contains(x.Id)).ToList();
    //        var keyEsgIssuesDictionary = companyKeyEsgIssues.ToDictionary(kei => kei.Id, kei => kei.KeyESGIssues);
    //        var subIndustryCodeDictionary = companyKeyEsgIssues.ToDictionary(kei => kei.Id, kei => kei.SubIndustryCode);

    //        var standardIndicatorsRepo = new RepositoryCollection<RPIndicatorExtended>(ClientDwConnectionString);
    //        var allStandardIndicators = standardIndicatorsRepo.ReadAllWhere(x => companyIds.Contains(x.CompanyId)).ToList();
    //        var standardIndicators = allStandardIndicators.GroupBy(a => a.CompanyId).ToDictionary(si => si.Key, si => si.ToList());

    //        var incidentsRepo = new RepositoryCollection<Incident>(ClientDwConnectionString);
    //        var allIncidents = incidentsRepo.ReadAllWhere(x => companyIds.Contains(x.CompanyId)).ToList();
    //        var incidents = allIncidents.GroupBy(a => a.CompanyId).ToDictionary(i => i.Key, i => i.ToList());

    //        var eventIndicatorsRepo = new RepositoryCollection<EventIndicator>(ClientDwConnectionString);
    //        var allEventIndicators = eventIndicatorsRepo.ReadAllWhere(x => companyIds.Contains(x.CompanyId)).ToList();
    //        var eventIndicators = allEventIndicators.GroupBy(a => a.CompanyId).ToDictionary(ei => ei.Key, ei => ei.ToList());


    //        var controversyIndicatorsRepo = new RepositoryCollection<RPControversyIndicator>(ClientDwConnectionString);
    //        var companyControversyIndicators = controversyIndicatorsRepo.ReadAllWhere(x => companyIds.Contains(x.CompanyId)).ToList();
    //        var controversyIndicators = companyControversyIndicators.GroupBy(a => a.CompanyId).ToDictionary(ci => ci.Key, ci => ci.ToList());

    //        var comparisonGroupControversyRepo = new RepositoryCollection<ComparisonGroupControversy>(ClientDwConnectionString);
    //        var companyComparisonGroupControversies = comparisonGroupControversyRepo.ReadAllWhere(x => companyIds.Contains(x.CompanyId)).ToList();
    //        var comparisonGroupControversies = companyComparisonGroupControversies.GroupBy(a => a.CompanyId).ToDictionary(cgc => cgc.Key, cgc => cgc.ToList());


    //        var sourcesRep = new RepositoryCollection<Source>(ClientDwConnectionString);
    //        var allSources = sourcesRep.ReadAllWhere(s => companyIds.Contains(s.CompanyId));
    //        var sources = allSources.GroupBy(s => s.CompanyId).ToDictionary(cs => cs.Key, cs => cs.OrderBy(s => s.SourceText).ToList());


    //        var crdos = new List<CompanyReportDataOffline>();

    //        foreach (var companyId in companyIds)
    //        {
    //            var keyEsgIssues = keyEsgIssuesDictionary.ContainsKey(companyId) ? keyEsgIssuesDictionary[companyId] : null;

    //            var subIndustryName = corporateData[companyId].GICSSubIndustry;
    //            var subIndustryCode = subIndustryCodeDictionary.ContainsKey(companyId)
    //                ? subIndustryCodeDictionary[companyId]
    //                : gicsSubIndustries.ContainsKey(subIndustryName)
    //                    ? gicsSubIndustries[subIndustryName]
    //                    : 0;

    //            var crdo = new CompanyReportDataOffline();

    //            crdo.CompanyId = companyId;

    //            crdo.ESGProfile = defaultEsgProfile;

    //            crdo.CorporateData = corporateData[companyId];
    //            crdo.ReferenceData = referenceData[companyId];
    //            crdo.FinancialData = financialData[companyId];

    //            crdo.OverallPerformance = companyPerformance.ContainsKey(companyId)
    //                ? companyPerformance[companyId].OverallPerformance
    //                : null;
    //            crdo.IndustryTopPerformers = companyPerformance.ContainsKey(companyId)
    //                ? companyPerformance[companyId].IndustryTopPerformers
    //                : new List<CompanyScore>();
    //            crdo.IndustryPeers = companyPerformance.ContainsKey(companyId)
    //                ? companyPerformance[companyId].IndustryPeers
    //                : new List<CompanyScore>();

    //            crdo.CompanyHistoricalPerformance = companyHistoricalPerformance.ContainsKey(companyId)
    //                ? companyHistoricalPerformance[companyId].Last36Months
    //                : new List<CompanyHistoryData>();

    //            crdo.Analyst = analysts.ContainsKey(corporateData[companyId].AnalystId)
    //                ? analysts[corporateData[companyId].AnalystId]
    //                : new Analyst();

    //            crdo.SubIndustryKeyEsgIssues = subIndustryKeyEsgIssues.ContainsKey(subIndustryCode)
    //                ? subIndustryKeyEsgIssues[subIndustryCode]
    //                : new List<SubIndustryKeyEsgIssue>();
    //            crdo.KeyEsgIssues = keyEsgIssues ?? new List<KeyEsgIssue>();

    //            crdo.IndicatorTemplates = indicatorTemplates;

    //            crdo.ThemesPerformance = companyPerformance.ContainsKey(companyId)
    //                ? companyPerformance[companyId].ThemesPerformance
    //                : new List<ThemePerformance>();

    //            crdo.StandardIndicators = standardIndicators.ContainsKey(companyId)
    //                ? standardIndicators[companyId]
    //                : new List<RPIndicatorExtended>();

    //            crdo.ControversyIndicators = controversyIndicators.ContainsKey(companyId)
    //                ? controversyIndicators[companyId]
    //                : new List<RPControversyIndicator>();

    //            crdo.ComparisonGroupControversies = comparisonGroupControversies.ContainsKey(companyId)
    //                ? comparisonGroupControversies[companyId]
    //                : new List<ComparisonGroupControversy>();

    //            crdo.EventIndicators = eventIndicators.Keys.Contains(companyId)
    //                ? eventIndicators[companyId]
    //                : new List<EventIndicator>();

    //            crdo.Incidents = incidents.Keys.Contains(companyId)
    //                ? incidents[companyId]
    //                : new List<Incident>();

    //            crdo.Sources = sources.ContainsKey(companyId)
    //                ? sources[companyId]
    //                : new List<Source>();


    //            //ComputeMarketCapitalization(crdo);

    //            crdos.Add(crdo);
    //        };

    //        return crdos;
    //    }
    //    //private static void ComputeMarketCapitalization(CompanyReportDataOffline crdo)
    //    //{
    //    //    double min = 0;
    //    //    double max = 0;

    //    //    if (crdo.IndustryPeers != null && crdo.IndustryPeers.Any())
    //    //    {
    //    //        var minMarkerCap = crdo.IndustryPeers.Min(p => p.MarketCapitalization);
    //    //        var maxMarkerCap = crdo.IndustryPeers.Max(p => p.MarketCapitalization);

    //    //        if (minMarkerCap > 0)
    //    //            min = minMarkerCap / 1000;

    //    //        if (maxMarkerCap > 0)
    //    //            max = maxMarkerCap / 1000;
    //    //    }

    //    //    crdo.IndustryPeersMinCapitalization = min;
    //    //    crdo.IndustryPeersMaxCapitalization = max;
    //    //}




    //    private IList<IndicatorTemplate> _indicatorTemplates { get; set; }

    //    private IDictionary<Guid, CorporateData> _corporateDataDictionary;
    //    private IDictionary<Guid, ReferenceData> _referenceDataDictionary;
    //    private IDictionary<Guid, FinancialData> _financialDataDictionary;

    //    private IDictionary<Guid, CompanyPerformance> companyPerformanceDic = new Dictionary<Guid, CompanyPerformance>();
    //    private IDictionary<Guid, CompanyHistoricalPerformance> _companyHistoricalPerformanceDictionary;

    //    private IDictionary<Guid, List<RPIndicatorExtended>> _standardIndicatorsDictionary;
    //    private IDictionary<Guid, List<RPControversyIndicator>> _controversyIndicatorsDictionary;
    //    private IDictionary<Guid, List<ComparisonGroupControversy>> _comparisonGroupControversiesDictionary;

    //    private IDictionary<Guid, List<EventIndicator>> _eventIndicatorsDictionary;
    //    private IDictionary<Guid, List<Incident>> _incidentsDictionary;

    //    private async Task PopulateCorporateData(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _corporateDataDictionary = await dataReader.GetCorporateDataDictionary(companyIds, cts.Token);
    //    }

    //    private async Task PopulateReferenceData(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _referenceDataDictionary = await dataReader.GetReferenceDataDictionary(companyIds, cts.Token);
    //    }

    //    private async Task PopulateFinancialData(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _financialDataDictionary = await dataReader.GetFinancialDataDictionary(companyIds, cts.Token);
    //    }

    //    private async Task PopulateIndicatorTemplates(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _indicatorTemplates = await dataReader.GetIndicatorTemplates(companyIds, cts.Token);
    //    }

    //    private async Task PopulateEventIndicators(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _eventIndicatorsDictionary = await dataReader.GetEventIndicatorsDictionary(companyIds, cts.Token);
    //    }

    //    private async Task PopulateIncidents(ClientDwDataReader dataReader, List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        _incidentsDictionary = await dataReader.GetIncidentsDictionary(companyIds, cts.Token);
    //    }

    //    #endregion 




    //    private async Task CompanyProfileSections(List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        var dataReader = new ClientDwDataReader();

    //        var tasks = new List<Task>();

    //        tasks.Add(PopulateCorporateData(dataReader, companyIds, cts));
    //        tasks.Add(PopulateReferenceData(dataReader, companyIds, cts));
    //        tasks.Add(PopulateFinancialData(dataReader, companyIds, cts));

    //        await Task.WhenAll(tasks.ToArray());
            
    //        if (cts.IsCancellationRequested)
    //            return;

    //        // to do generate company profile sections

    //    }

    //    private async Task ControversiesSections(List<Guid> companyIds, CancellationTokenSource cts)
    //    {
    //        var dataReader = new ClientDwDataReader();
    //        var reportsRepository = new ReportsRepository();

    //        var tasks = new List<Task>();

    //        tasks.Add(PopulateIndicatorTemplates(dataReader, companyIds, cts));
    //        tasks.Add(PopulateEventIndicators(dataReader, companyIds, cts));
    //        tasks.Add(PopulateIncidents(dataReader, companyIds, cts));

    //        await Task.WhenAll(tasks.ToArray());

    //        if (cts.IsCancellationRequested)
    //            return;

    //        foreach(var companyId in companyIds)
    //        {
    //            var dataSource = new CompanyReportDataOffline
    //            {
    //                ReportType = ReportGenerator.BL.ReportType.CompanyReport,
    //                CompanyId = companyId,

    //                CorporateData = _corporateDataDictionary[companyId],
    //                FinancialData = _financialDataDictionary[companyId],

    //                IndicatorTemplates = _indicatorTemplates,

    //                EventIndicators = _eventIndicatorsDictionary.Keys.Contains(companyId)
    //                    ? _eventIndicatorsDictionary[companyId]
    //                    : new List<EventIndicator>(),

    //                Incidents = _incidentsDictionary.Keys.Contains(companyId)
    //                    ? _incidentsDictionary[companyId]
    //                    : new List<Incident>(),
    //            };

    //            var documentGenerator = new ControversiesSection();
    //            var result = documentGenerator.GeneratePdfDocument(dataSource);

    //            var section = new ControversiesReportSection
    //            {
    //                Id = companyId,
    //                PdfDocument = result.PdfDocument,
    //                OutlinePositions = result.OutlinePositions,
    //                PageElementPositions = result.PageElementPositions
    //            };

    //            await reportsRepository.SaveControversiesReportSection(section, cts.Token);

    //        }
    //    }


    //    public ExecutionResult ExecuteBulkPdfReports(ReportOptions options)
    //    {
    //        var cts = new CancellationTokenSource();
            
    //        if (options.ExecuteAll)
    //        {
    //            var dataReader = new ClientDwDataReader();

    //            var companyIds = dataReader.GetCompanyIds(cts.Token).Result;

    //            foreach (var ids in companyIds.Batch(100))
    //            {
    //                var task = CompanyProfileSections(ids, cts);
    //                task.Wait(cts.Token);


    //                var controversies = ControversiesSections(ids, cts);
    //                controversies.Wait(cts.Token);
    //            }



    //        }

    //        if (options.CorporateDataWereUpdated)
    //        {

    //        }
    //        if (options.RpProfilesWereFinalized)
    //        {

    //        }
    //        if (options.EventsProfilesWerePublished)
    //        {

    //        }
    //        if (options.GcProfilesWerePublished)
    //        {

    //        }

    //        return null;
    //    }
    //}
}
